package org.springbatch.concept.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.NonUniqueObjectException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springbatch.concept.domain.BaseEntity;
import org.springbatch.concept.domain.BaseType;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateSystemException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;


public class BaseDAOHibernate  extends HibernateDaoSupport{

	public BaseDAOHibernate(){
	}
	@SuppressWarnings(value = "unchecked")
	public <T> T findById(Class<T> entityClass, Serializable id) throws DataAccessException {
		return (T) getHibernateTemplate().get(entityClass, id);
	}
	public void save(BaseEntity entity) throws DataAccessException {
		try {
			getHibernateTemplate().saveOrUpdate(entity);
		}
		catch (HibernateSystemException systemExc) {
			if (systemExc.getRootCause() instanceof NonUniqueObjectException) {
				getHibernateTemplate().merge(entity);			
			}
			else
				throw systemExc;
		}
	}
	public Object update(BaseEntity entity) throws DataAccessException {
		return getHibernateTemplate().merge(entity);
	}
	public <T> void delete(T entity) throws DataAccessException {
		getHibernateTemplate().delete(entity);
	}
	@SuppressWarnings(value = "unchecked")
	public <T> List<T> findByExample(T exampleEntity) throws DataAccessException {
		return (List<T>) getHibernateTemplate().findByExample(exampleEntity);
	}

	@SuppressWarnings(value = "unchecked")
	public <T> List<T> find(Class<T> entityClass, String queryString, Object[] params) {
		return (List<T>) getHibernateTemplate().find(queryString, params);
	}
	@SuppressWarnings(value = "unchecked")
	public <T> List<T> find(Class<T> entityClass, String queryString) {
		return (List<T>) getHibernateTemplate().find(queryString);
	}
	
	public void initializeProxy(Object proxy) {
        // TODO Auto-generated method stub
        getHibernateTemplate().initialize(proxy);
    }

	public <T> List<T> findLimitedResult(String queryString, int start, int max) {
		return findLimitedResult(queryString, start, max, null);
	}
	@SuppressWarnings(value = "unchecked")
	public <T> T findUniqueResult(String queryString) {		
		return (T)findUniqueResult(queryString, null);
	}
	@SuppressWarnings(value = "unchecked")
	public <T> T findUniqueResult(String queryString, Object[] params) {
		Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();
		Query query = session.createQuery(queryString);
		applyParamsToQuery(query, params);
		query.setFirstResult(0);
		query.setMaxResults(1);
		return (T)query.uniqueResult();
	}	
	@SuppressWarnings(value = "unchecked")
	public <T> List<T> findLimitedResult(String queryString, int start, int max, Object[] params) {
		Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();
		Query query = session.createQuery(queryString);
		applyParamsToQuery(query, params);
		query.setFirstResult(start);
		query.setMaxResults(max);
		return (List<T>)query.list();
	}
	
	private void applyParamsToQuery(Query query, Object params[]) {
		int i, n;
		if (params==null) return;
		if (params.length<=0) return;
		n = params.length;
		for(i=0;i<n;i++)
			query.setParameter(i, params[i]);
	}

	public void saveType(BaseType entity) throws DataAccessException {
		try {
			getHibernateTemplate().saveOrUpdate(entity);
		} catch (HibernateSystemException systemExc) {
			if (systemExc.getRootCause() instanceof NonUniqueObjectException) {
				getHibernateTemplate().merge(entity);
			}
			else
				throw systemExc;
		}
	}
	
}
